using System.Text;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using SPI.AgentServer.Configuration;
using SPI.AgentServer.Models;

namespace SPI.AgentServer.Services.AI;

/// <summary>
/// Qwen2.5 大模型客户端实现
/// 负责与 Qwen 模型服务进行 HTTP 通信
/// </summary>
public class QwenClient : IQwenClient
{
    private readonly HttpClient _httpClient;
    private readonly QwenConfiguration _config;
    private readonly ILogger<QwenClient> _logger;

    public QwenClient(HttpClient httpClient, IOptions<QwenConfiguration> options, ILogger<QwenClient> logger)
    {
        _httpClient = httpClient;
        _config = options.Value;
        _logger = logger;
        // 设置 Qwen 服务的基础地址和超时时间
        _httpClient.BaseAddress = new Uri(_config.BaseUrl);
        _httpClient.Timeout = TimeSpan.FromSeconds(Math.Min(_config.Timeout, 30)); // 最多30秒，防止卡死
        _logger.LogInformation("QwenClient 初始化，超时时间: {Timeout}秒", _httpClient.Timeout.TotalSeconds);
    }

    /// <summary>
    /// 调用 Qwen 模型的聊天完成接口
    /// </summary>
    /// <param name="request">包含对话消息的请求对象</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>模型的响应结果</returns>
    public async Task<QwenResponse> ChatCompletionAsync(QwenRequest request, CancellationToken cancellationToken = default)
    {
        const int maxRetries = 2; // 降低重试次数：从3次改为2次
        var retryDelays = new[] { 1000, 2000 }; // 缩短等待时间：1秒、2秒

        for (int attempt = 0; attempt <= maxRetries; attempt++)
        {
            try
            {
                // 使用配置中的默认值填充请求参数
                request.Model = _config.Model;
                request.MaxTokens ??= _config.MaxTokens;
                request.Temperature ??= _config.Temperature;

                var json = JsonConvert.SerializeObject(request);
                var content = new StringContent(json, Encoding.UTF8, "application/json");

                _logger.LogInformation("📤 发送请求到 Qwen API (第 {Attempt}/{MaxAttempts} 次)", 
                    attempt + 1, maxRetries + 1);

                // 检查是否已取消
                cancellationToken.ThrowIfCancellationRequested();

                var response = await _httpClient.PostAsync("/v1/chat/completions", content, cancellationToken);

                _logger.LogInformation("📥 收到 Qwen API 响应，状态码: {StatusCode}", (int)response.StatusCode);

                var responseContent = await response.Content.ReadAsStringAsync(cancellationToken);

                if (!response.IsSuccessStatusCode)
                {
                    _logger.LogError("Qwen API returned error. Status: {StatusCode}, Response Body: {Content}",
                        (int)response.StatusCode, responseContent);
                    
                    // 如果是客户端错误（4xx），不重试
                    if ((int)response.StatusCode >= 400 && (int)response.StatusCode < 500)
                    {
                        throw new HttpRequestException($"Qwen API error {response.StatusCode}: {responseContent}");
                    }
                    
                    // 服务器错误（5xx）或其他错误，尝试重试
                    if (attempt < maxRetries)
                    {
                        _logger.LogWarning("⚠️ Qwen API 请求失败，第 {RetryCount} 次重试（{Delay}毫秒后）...", 
                            attempt + 1, retryDelays[attempt]);
                        await Task.Delay(retryDelays[attempt], cancellationToken);
                        continue;
                    }
                    
                    throw new HttpRequestException($"Qwen API error {response.StatusCode}: {responseContent}");
                }

                _logger.LogDebug("Received response from Qwen API: {Content}", responseContent);

                var qwenResponse = JsonConvert.DeserializeObject<QwenResponse>(responseContent);

                if (qwenResponse == null)
                {
                    throw new InvalidOperationException("Failed to deserialize Qwen response");
                }

                // 成功，记录日志
                if (attempt > 0)
                {
                    _logger.LogInformation("✅ Qwen API 请求在第 {Attempt} 次尝试后成功", attempt + 1);
                }

                return qwenResponse;
            }
            catch (HttpRequestException) when (attempt >= maxRetries)
            {
                throw;
            }
            catch (HttpRequestException ex)
            {
                _logger.LogWarning(ex, "⚠️ HTTP 请求失败，第 {RetryCount} 次重试（{Delay}毫秒后）...", 
                    attempt + 1, retryDelays[attempt]);
                
                if (attempt < maxRetries)
                {
                    await Task.Delay(retryDelays[attempt], cancellationToken);
                    continue;
                }
                
                _logger.LogError(ex, "❌ HTTP request to Qwen API failed after {MaxRetries} retries", maxRetries + 1);
                throw new InvalidOperationException($"Failed to communicate with Qwen API after {maxRetries + 1} attempts", ex);
            }
            catch (TaskCanceledException ex)
            {
                _logger.LogError(ex, "Request to Qwen API timed out");
                throw new InvalidOperationException("Qwen API request timed out", ex);
            }
        }

        // 这行代码理论上不会被执行，但编译器需要
        throw new InvalidOperationException("Unexpected error in retry logic");
    }

    /// <summary>
    /// 获取结构化的模型响应
    /// 将模型返回的内容解析为结构化的对象（包含思考过程、工具调用或直接回答）
    /// </summary>
    /// <param name="prompt">用户的提示词</param>
    /// <param name="cancellationToken">取消令牌</param>
    /// <returns>结构化的模型响应</returns>
    public async Task<ModelResponse> GetStructuredResponseAsync(string prompt, CancellationToken cancellationToken = default)
    {
        var request = new QwenRequest
        {
            Messages = new List<QwenMessage>
            {
                new QwenMessage { Role = "user", Content = prompt }
            }
        };

        var response = await ChatCompletionAsync(request, cancellationToken);
        
        if (response.Choices == null || response.Choices.Count == 0)
        {
            throw new InvalidOperationException("No response from model");
        }

        var content = response.Choices[0].Message.Content;
        _logger.LogDebug("Model response: {Content}", content);
        
        try
        {
            // 清理响应内容，去除可能的额外文字
            content = content.Trim();
            
            // 尝试提取JSON部分（如果响应包含额外文字）
            var jsonStartIndex = content.IndexOf('{');
            var jsonEndIndex = content.LastIndexOf('}');
            
            if (jsonStartIndex >= 0 && jsonEndIndex > jsonStartIndex)
            {
                var jsonContent = content.Substring(jsonStartIndex, jsonEndIndex - jsonStartIndex + 1);
                
                // Try to parse as JSON
                var modelResponse = JsonConvert.DeserializeObject<ModelResponse>(jsonContent);
                if (modelResponse != null)
                {
                    return modelResponse;
                }
            }
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Failed to parse model response as JSON, treating as direct answer: {Content}", content);
        }

        // 如果解析失败，尝试从内容中生成SQL
        if (content.Contains("SELECT", StringComparison.OrdinalIgnoreCase))
        {
            // 尝试提取SQL语句
            var sqlMatch = System.Text.RegularExpressions.Regex.Match(content, @"SELECT.*?(?:FROM.*?)?(?:WHERE.*?)?(?:GROUP BY.*?)?(?:ORDER BY.*?)?(?:LIMIT.*?)?(?:;|$)", 
                System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline);
            
            if (sqlMatch.Success)
            {
                return new ModelResponse
                {
                    Action = new ToolInstruction
                    {
                        Tool = "execute_sql",
                        Parameters = new Dictionary<string, object>
                        {
                            ["sql"] = sqlMatch.Value.TrimEnd(';'),
                            ["databaseName"] = "Test"
                        }
                    }
                };
            }
        }

        return new ModelResponse
        {
            DirectAnswer = content
        };
    }
}
